package com.goldsprite.gameframeworks.simplephys.collis;

import com.goldsprite.gameframeworks.simplephys.shape.PhysCircle;
import com.goldsprite.gameframeworks.utils.math.Vector2;

import static com.goldsprite.gameframeworks.simplephys.collis.CollisionUtils.safeDistance;

public class CircleCircleCollisionDetector implements CollisionDetector<PhysCircle, PhysCircle> {

	/**
	 * 连续碰撞检测(CCD)方法 - 用于快速移动的圆
	 * 基于圆的运动轨迹计算第一次碰撞的时间点
	 */
	public boolean ccdCollision(Vector2 lastPos, PhysCircle a, PhysCircle b, CollisionResult result) {
		if(CollisionUtils.isResetCalc) result.reset();

		// 获取移动圆的起点和终点位置
		float startX = lastPos.x;
		float startY = lastPos.y;
		float endX = a.x;
		float endY = a.y;

		// 静止圆的位置
		float statX = b.x;
		float statY = b.y;

		// 半径和
		float radiusSum = a.radius + b.radius;

		// 计算运动向量和相对位置向量
		float dx = endX - startX;
		float dy = endY - startY;
		float u = statX - startX;
		float v = statY - startY;

		// 计算系数
		float L2 = dx * dx + dy * dy;  // 运动距离的平方
		float M = u * dx + v * dy;     // 点积
		float N = u * u + v * v - radiusSum * radiusSum; // 初始距离平方 - 半径和平方

		// 如果L2为0，说明圆没有移动，使用静态检测
		if (L2 == 0) {
			return calculateCollision(a, b, result);
		}

		// 计算判别式
		float discriminant = M * M - L2 * N;

		// 无实数解，没有碰撞
		if (discriminant < 0) {
			return false;
		}

		// 计算碰撞时间 t
		float sqrtDisc = (float) Math.sqrt(discriminant);
		float t = (M - sqrtDisc) / L2;

		// 碰撞时间必须在 [0,1] 范围内
		if (t < 0 || t > 1) {
			return false;
		}

		// 计算碰撞时的位置
		float collisionX = startX + t * dx;
		float collisionY = startY + t * dy;

		// 设置碰撞结果
		result.collided = true;

		// 计算碰撞法向量（从静止圆指向移动圆）, 在这里应直接使用反向速度做法向量
//		float normalX = -dx;
//		float normalY = -dy;
//		float normalLength = (float) Math.sqrt(normalX * normalX + normalY * normalY);
		float normalX = collisionX - statX;
		float normalY = collisionY - statY;
		float normalLength = (float) Math.sqrt(normalX * normalX + normalY * normalY);

		float dx2 = endX - collisionX;
		float dy2 = endY - collisionY;
		float depth = (float) Math.sqrt(dx2 * dx2 + dy2 * dy2) + safeDistance;

		if (normalLength == 0) {
			// 特殊情况：完全重合
			result.normal.set(-1, 0);
			result.depth = radiusSum;
		} else {
			// 归一化法向量
			result.normal.set(normalX / normalLength, normalY / normalLength);
			result.depth = depth;
		}

		// 可选：记录碰撞时间，用于物理模拟
		//result.collisionTime = t;

		return true;
	}

	/**
	 * 高性能版本的圆形碰撞检测（避免开方运算）
	 */
	@Override
	public boolean calculateCollision(PhysCircle a, PhysCircle b, CollisionResult result) {
		if(CollisionUtils.isResetCalc) result.reset();

		// 计算圆心距离的平方
		float dx = b.x - a.x;
		float dy = b.y - a.y;
		float distanceSquared = dx * dx + dy * dy;

		// 计算半径和的平方
		float radiusSum = a.radius + b.radius;
		float radiusSumSquared = radiusSum * radiusSum;

		// 检查是否碰撞
		if (distanceSquared > radiusSumSquared) {
			return false;
		}

		result.collided = true;

		// 只有确实发生碰撞时才计算开方
		float distance = (float) Math.sqrt(distanceSquared);

		if (distance == 0)
			result.normal.set(-1, 0);// 完全重合
		else
			result.normal.set(-dx / distance, -dy / distance);// 正常碰撞
		result.depth = radiusSum - distance;
		result.depth += CollisionUtils.safeDistance;

		return true;
	}
}
